from urllib.parse import unquote
import redis
from beanie import WriteRules
import re
from beanie.odm.operators.find.comparison import In
from beanie.odm.operators.find.logical import Or
from fastapi import Depends
from core import config
from core.logger import log
from db.models.chat_message import ChatMessageModel
from db.models.wx_friends import WxFriendsModel, WxId
from typing import List
from utils.result import Result
from utils.sender_tools import SenderTools
from utils.wechat_pad_tools import WeChatPadClient


async def create_wx_friends(auth_key: str, device_id: str):
    """
    插入单条用户数据到数据库
    :param device_id:
    :param auth_key:
    :return: 插入结果
    """
    try:
        wx_cli = WeChatPadClient()
        # 获取所有设备好友列表
        frds = wx_cli.get_friends_list(auth_key)
        # if not frds:
        #     return Result.fail(msg="获取好友列表失败")
        # 只查询 wx_id 字段，减少内存消耗
        existing_ids = await (WxFriendsModel.
                              find(WxFriendsModel.device_id == device_id,
                                   projection_model=WxId).to_list())

        wx_ids_set = {item.wx_id for item in existing_ids}

        new_fds = []
        for frd in frds:
            user_name = frd.get("userName", {}).get("str")
            if not user_name or user_name in wx_ids_set:
                continue

            new_fd = {
                "device_id": device_id,
                "wx_id": user_name,
                "nickname": frd.get("nickName", {}).get("str", ""),
                "avatar": frd.get("smallHeadImgUrl", ""),
                "remark": frd.get("remark", {}).get("str", ""),
                "desc": frd.get("description", "")
            }
            new_fds.append(new_fd)

        if new_fds:
            documents = [WxFriendsModel(**item) for item in new_fds]
            await WxFriendsModel.insert_many(documents)

        return Result.success(data=new_fds)
    except Exception as e:
        log.exception(f"插入失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="导入失败")

async def create_rag_friends(device_id: str,):
    try:
        new_fd = {
            "device_id": device_id,
            "wx_id": f"wx_id_test_{device_id.split('_')[1]}",
            "nickname": f"test_{device_id.split('_')[1]}",
            "avatar": "",
            "remark": "",
            "desc": ""
        }
        await WxFriendsModel(**new_fd).insert()
    except Exception as e:
        log.exception(f"插入失败: {type(e).__name__}, 错误详情: {str(e)}")

async def get_fd_by_wx_id(wx_id: str, device_id: str):
    try:
        wx_fd = await WxFriendsModel.find_one(WxFriendsModel.wx_id == wx_id, WxFriendsModel.device_id == device_id)
        return wx_fd
    except Exception as e:
        print(f"查询失败: {e}")
        return []

async def get_specified_friends(conditions: str,device_id: str):
    """
    获取指定条件下的所有好友
    :param conditions: 指定备注中的信息以conditions开头
    :return: 好友列表
    """
    try:
        wx_fds = await WxFriendsModel.find(WxFriendsModel.device_id==device_id,projection_model=WxId).to_list()
        wx_fds = [item.wx_id for item in wx_fds if re.match(f"^{conditions}", item.remark)]
        return wx_fds
    except Exception as e:
        print(f"查询失败: {e}")
        return []


async def get_friends_by_nickname(device_id: str, nickname: str = None, tag: str = None):
    """
    根据设备ID获取好友列表，如果传了nickname，则进行模糊查询

    :param tag:
    :param device_id: 设备ID
    :param nickname: 好友昵称，可选，如果不传则返回所有好友
    :return: 好友列表
    """
    try:
        # 构建查询条件
        find_query = {"device_id": device_id}

        # 如果传了nickname，则添加模糊查询条件
        if nickname:
            nickname = unquote(nickname)
            pattern = re.compile(f".*{re.escape(nickname)}.*", re.IGNORECASE)
            # 使用正则表达式进行模糊匹配（不区分大小写）
            find_query["nickname"] = pattern
        if tag:
            find_query["tags"] = tag


            # 执行查询
        wx_friends = await WxFriendsModel.find(find_query).to_list()

        return Result.success(data=wx_friends)
    except Exception as e:
        log.exception(f"查询好友列表失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="查询好友列表失败")

async def set_friends_tag(device_id: str,  wx_ids: List[str], tag: str):
    """
    为指定好友设置标签
    :param device_id: 设备ID
    :param wx_ids: 好友ID
    :param tag: 标签
    :return: 设置结果
    """
    try:
        # 使用 MongoDB 的 $addToSet 操作符直接向数组添加标签
        result = await WxFriendsModel.find(
            WxFriendsModel.device_id == device_id,
            In(WxFriendsModel.wx_id, wx_ids)
        ).update({"$addToSet": {"tags": tag}})

        if result.modified_count > 0:
            return Result.success(msg=f"成功为{result.modified_count}个好友添加标签")
        else:
            return Result.success(msg="标签已存在或未找到匹配的好友")

    except Exception as e:
        log.exception(f"批量设置标签失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="批量设置标签失败")

async def remove_friends_tag(device_id: str, wx_ids: List[str], tag: str):
    """
    为指定好友删除标签
    :param device_id: 设备ID
    :param wx_ids: 好友ID列表
    :param tag: 要删除的标签
    :return: 删除结果
    """
    try:
        # 使用 MongoDB 的 $pull 操作符从数组中删除标签
        result = await WxFriendsModel.find(
            WxFriendsModel.device_id == device_id,
            In(WxFriendsModel.wx_id, wx_ids)
        ).update({"$pull": {"tags": tag}})

        if result.modified_count > 0:
            return Result.success(msg=f"成功为{result.modified_count}个好友删除标签")
        else:
            return Result.success(msg="未找到匹配的标签或好友")

    except Exception as e:
        log.exception(f"批量删除标签失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="批量删除标签失败")

async def get_friend_nickname(friend_wx_id:str,device_id:str):
    try:
        result = await WxFriendsModel.find_one(WxFriendsModel.wx_id == friend_wx_id,WxFriendsModel.device_id == device_id)
        if result:
            return result.nickname
    except Exception as e:
        log.exception(f"获取好友昵称失败: {type(e).__name__}, 错误详情: {str(e)}")
        return None




# 创建全局 Redis 客户端实例

redis_client = redis.Redis(
    host=config.settings.REDIS_HOST,  # 根据实际情况修改
    port=config.settings.REDIS_PORT,         # 根据实际情况修改
    db=3,
    password=config.settings.REDIS_PASSWORD,# 根据实际情况修改
    decode_responses=True  # 自动解码响应
)

async def add_tag(tag: str):
    """
    添加全局标签
    :param tag: 标签名
    :return: 添加结果
    """
    try:
        # 使用 Redis Set 存储全局标签，保证唯一性
        key = "global_tags"
        result = redis_client.sadd(key, tag)

        if result:
            return Result.success(msg=f"标签'{tag}'添加成功")
        else:
            return Result.success(msg=f"标签'{tag}'已存在")
    except Exception as e:
        log.exception(f"添加标签失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="添加标签失败")


async def remove_tag(tag: str):
    """
    删除全局标签

    :param tag: 标签名
    :return: 删除结果
    """
    try:
        key = "global_tags"
        result = redis_client.srem(key, tag)

        if result:
            return Result.success(msg=f"标签'{tag}'删除成功")
        else:
            return Result.success(msg=f"标签'{tag}'不存在")
    except Exception as e:
        log.exception(f"删除标签失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="删除标签失败")


async def get_tags():
    """
    获取所有全局标签列表

    :return: 标签列表
    """
    try:
        key = "global_tags"
        tags = redis_client.smembers(key)
        # 如果 decode_responses=True，则不需要手动解码
        tags_list = list(tags) if isinstance(tags, list) else [t for t in tags]
        return Result.success(data=tags_list)
    except Exception as e:
        log.exception(f"获取标签列表失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="获取标签列表失败")

async def get_friend_detail(key: str, wx_id: str, device_id: str):

    """
    获取指定好友的详细信息
    :param key: 用户设备码
    :param device_id: 设备ID（用户自己的微信号）
    :param wx_id: 好友ID
    :return: 好友详细信息
    """
    try:
        remark = await get_friend_remark(wx_id, device_id)
        wx_cli = WeChatPadClient()
        info = wx_cli.get_detail_friend_info(key, wx_id)
        info["remark"]["str"] = remark if remark else info["remark"].get("str", "")
        return Result.success(data=info)
    except  Exception as e:
        log.exception(f"获取好友详细信息失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="获取好友详细信息失败")

async def set_friends_remark(device_id: str, wx_id: str, remark: str):
    """
    为指定好友设置备注
    :param device_id: 设备ID
    :param wx_id: 目标好友ID
    :param remark: 备注内容
    :return: 设置结果
    """
    try:
        #使用MongoDB的$set操作符
        result = await WxFriendsModel.find(
            WxFriendsModel.device_id == device_id,
            WxFriendsModel.wx_id == wx_id
        ).set({"remark": remark})
        if result.modified_count > 0:
            return Result.success(msg="设置备注成功")
        else:
            return Result.success(msg="未找到匹配的好友")
    except Exception as e:
        log.exception(f"设置备注失败: {type(e).__name__}, 错误详情: {str(e)}")
        return Result.fail(msg="设置备注失败")



async def get_friend_remark(wx_id,device_id):
        """
        获取朋友备注信息
        """
        try:
            fr = await WxFriendsModel.find_one(WxFriendsModel.wx_id == wx_id,WxFriendsModel.device_id == device_id)
            return fr.remark
        except Exception as e:
            log.exception(f"获取朋友备注信息失败: {type(e).__name__}, 错误详情: {str(e)}")
            return None


async def get_friends_with_chat_history(device_id: str):
    """
    获取有历史聊天记录的所有朋友
    :param device_id: 设备ID
    :return:
    """
    try:
        # 查找与该设备ID相关的所有聊天记录（作为发送者或接收者）
        messages = await ChatMessageModel.find(
            Or(
                ChatMessageModel.sender_id == device_id,
                ChatMessageModel.receiver_id == device_id
            )
        ).to_list()

        # 提取所有相关的好友ID
        friend_ids = set()
        for msg in messages:
            if msg.sender_id == device_id:
                friend_ids.add(msg.receiver_id)
            else:
                friend_ids.add(msg.sender_id)
        # 获取这些好友的详细信息
        friends = await WxFriendsModel.find(
            In(WxFriendsModel.wx_id, list(friend_ids)), WxFriendsModel.device_id == device_id
        ).to_list()
        return Result.success(data=friends)
    except Exception as e:
        # 根据实际日志系统记录异常信息
        log.exception(f"获取有历史聊天记录的所有朋友失败: {type(e).__name__}, 错误详情: {str(e)}")
        return  None



async def delete_wx_friends(device_id: str):
    """删除微信朋友"""
    try:
        await WxFriendsModel.find_one(WxFriendsModel.device_id == device_id).delete()
        return True
    except Exception as e:
        # 根据实际日志系统记录异常信息
        log.exception(f"删除微信朋友失败: {type(e).__name__}, 错误详情: {str(e)}")
        return False

async def get_rag_detail(wx_id: str,device_id: str):
    fr = await get_fd_by_wx_id(wx_id,device_id)
    data = {
        "userName": {
            "str": fr.wx_id
        },
        "nickName": {
            "str": fr.nickname
        },
        "pyinitial": {
            "str": "111"
        },
        "quanPin": {
            "str": "ce'shi"
        },
        "sex": 0,
        "imgBuf": {
            "len": 0
        },
        "bitMask": 4294967295,
        "bitVal": 3,
        "imgFlag": 3,
        "remark": {
            "str": fr.remark
        },
        "remarkPyinitial": {},
        "remarkQuanPin": {},
        "contactType": 0,
        "roomInfoCount": 0,
        "domainList": {},
        "chatRoomNotify": 0,
        "addContactScene": 0,
        "signature": "",
        "personalCard": 1,
        "hasWeiXinHdHeadImg": 1,
        "verifyFlag": 0,
        "level": 0,
        "source": 1000030,
        "alias": fr.wx_id,
        "weiboFlag": 0,
        "albumStyle": 0,
        "albumFlag": 0,
        "snsUserInfo": {
            "sns_flag": 1,
            "sns_bgimg_id": "https://img95.699pic.com/xsj/0r/xi/n4.jpg!/fw/700/watermark/url/L3hzai93YXRlcl9kZXRhaWwyLnBuZw/align/southeast",
            "sns_bgobject_id": 14274580497727689000,
            "sns_flagex": 128,
            "sns_privacy_recent": 0
        },
        "bigHeadImgUrl": "https://img95.699pic.com/xsj/0r/xi/n4.jpg!/fw/700/watermark/url/L3hzai93YXRlcl9kZXRhaWwyLnBuZw/align/southeast",
        "smallHeadImgUrl": "https://img95.699pic.com/xsj/0r/xi/n4.jpg!/fw/700/watermark/url/L3hzai93YXRlcl9kZXRhaWwyLnBuZw/align/southeast",
        "myBrandList": "<brandlist count=\"0\" ver=\"876746089\"></brandlist>",
        "customizedInfo": {
            "brand_flag": 0
        },
        "headImgMd5": "ffcdc298cb344c1a5854806582c7bf04",
        "encryptUserName": "v3_020b3826fd0301000000000098760f8f0197b4000000501ea9a3dba12f95f6b60a0536a1adb6a8c5be452c0e73521ef31467d681e7ac660e0bcd955c6bff32f704a75cdc0b285465fc3c785bd55a2e3e81e19a46652b547cce1381fe05e4e4d8e348c5@stranger",
        "additionalContactList": {
            "item": {}
        },
        "chatroomVersion": 0,
        "chatroomMaxCount": 0,
        "chatroomAccessType": 0,
        "newChatroomData": {
            "member_count": 0,
            "info_mask": 0,
            "unknow": {}
        },
        "deleteFlag": 0,
        "phoneNumListInfo": {
            "count": 0
        },
        "chatroomInfoVersion": 0,
        "deleteContactScene": 0,
        "chatroomStatus": 0,
        "extFlag": 0
    }
    return data
